package it.greg.findparty.model;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import it.greg.findparty.android.util.GestoreErrori;
import it.greg.findparty.util.*;
import android.util.Log;

public class GestoreEventi {

	private GestoreErrori errManager;
	private HtmlUtil htmlUtil;
	private String citta;
	private String tipo;
	
	public GestoreEventi(GestoreErrori e){
		this(); //Calls GestoreEventi()
		this.errManager = e;
		//this.htmlUtil.setGestoreErrori(e);
	}
	
	public GestoreEventi() {
		this.htmlUtil = new HtmlUtil();
		//Valori di default
		this.citta = "roma";
		this.tipo = "";
		this.errManager = null;
	}
	
	public void setGestoreErrori(GestoreErrori e){
		this.errManager = e;
	}
	
	public void setCitta(String citta) {
		this.citta = citta.toLowerCase();
	}
	
	public void setTipo(String tipo){
		this.tipo = tipo.toLowerCase();
	}
	
	public void setOra(String time){
		if (time==null)
			time = "orario_dopo_le_20";
		//Richiesta http per far settare il cookie giusto
		this.htmlUtil.getHTML("http://www.bobobo.it/roma/eventi/"+time);
	}
	
	public void setData(String data){
		if (data==null)
			data = "oggi";
		//Richiesta http per far settare il cookie giusto
		this.htmlUtil.getHTML("http://www.bobobo.it/roma/eventi/data-"+data);
	}
	
	/*
	 * Ritorna una lista di oggetti Evento, presa da bobobo.it riguardanti il
	 * giorno corrente.
	 */
	public List<Evento> getEventi() {
		String html = this.htmlUtil.getHTML("http://www.bobobo.it/"+this.citta+"/eventi/"+this.tipo);
		List<Evento> listEventi = null;
		if (html!=null)
			listEventi = parseHTML(html);
		return listEventi;
	}

	/*
	 * Metodo che costruisce a partire da codice html una lista di oggetti
	 * Evento.
	 */
	private List<Evento> parseHTML(String html) {
		String data, ora, titolo, descrizione, indirizzo;
		Evento evento;
		List<Evento> list = new ArrayList<Evento>();
		int i = 0;
		if (html.indexOf("startDate", 0) == -1){
			if (this.errManager!=null)
				this.errManager.showError("Nessun evento trovato!");
			return null;
		}
		try {
			int end = html.lastIndexOf("margin-top: 10px") - 50;
			Log.i("ciclo", i+"<"+end);
			int old_i = 0;
			while (true) {
				i = html.indexOf("startDate", i)+20;
				if (i < old_i) break;
				data = html.substring(i, html.indexOf(" - ", i));
				//Log.i("data", data);
				int tmp = html.indexOf("\">", i);
				ora = html.substring(tmp-5,tmp);
				if (!(ora.contains(":")))
					ora = "??";
				//Log.i("ora", ora);
				i = html.indexOf("name\">", i) + 6;
				titolo = html.substring(i, html.indexOf("</span>", i));
				//Log.i("titolo", titolo);
				i = html.indexOf("name\">", i) + 6;
				indirizzo = html.substring(i, html.indexOf("</span>", i));
				//Log.i("indirizzo", indirizzo);
				i = html.indexOf("description\">", i) + 13;
				descrizione = html.substring(i, html.indexOf("</span>", i));
				//Log.i("desc", descrizione);
				evento = new Evento();
				evento.setData(filter(data));
				evento.setDescrizione(filter(descrizione));
				evento.setIndirizzo(filter(indirizzo));
				evento.setOra(filter(ora));
				evento.setTitolo(filter(titolo));
				list.add(evento);
				//Log.i("posiz.", html.substring(i,i+100));
				old_i = i;
			}
		} catch (Exception e) {
			if (this.errManager!=null)
				this.errManager.showError("Errore parser:\n"+e.getMessage());
			return null;
		}
		return list;
	}
	
	/*
	 * Funzione per ripulire una stringa da caratteri speciali
	 */
	private String filter(String s){
		String result = s.replace("\t", "");
		result = result.replace("&agrave;", "à");
		result = result.replace("&Agrave;", "à");
		result = result.replace("&egrave;", "è");
		result = result.replace("&igrave;", "ì");
		result = result.replace("&ograve;", "ò");
		result = result.replace("&ugrave;", "ù");
		result = result.replace("&nbsp;", " ");
		result = result.replace("”", "\"");
		result = result.replace("’", "\'");
		result = result.replace("&deg;", "°");
		result = result.replace("&quot;", "\"");
		result = result.replace("&eacute;", "é");
		result = result.replace("&bull;", "•");
		result = result.replace("&amp;", "&");
		result = result.replace("&euro;", "€");
		result = result.replace("&oacute;", "ó");
		result = result.replace("&Oacute;", "Ó");
		result = result.replace("&dagger;", "†");
		result = result.replace("&oslash;", "ø");
		result = result.replace("&Oslash;", "Ø");
		result = result.replace("&ndash;", "–");
		result = result.replace("&gt;", ">");
		result = result.replace("&lt;", "<");
		result = result.replace("&Idquo;", "\"");
		result = result.replace("&Isquo;", "'");
		result = result.replace("&rsquo;", "'");
		result = result.replace("&rdquo;", "\"");
		//TODO maybe is better remove others: &something;
		return result;
	}
	
	//Ritorna una mappa <Evento, Integer> ordinata per Integer
	//dove Integer rappresenta la distanza tra sourceAddr e l'indirizzo
	//dell'evento.
	public Map<Evento, Integer> getOrderedEventi(String sourceAddr) {
		List<Evento> listaEventi = this.getEventi();
		OrdinaEventi eventiOrdinati = null;
		if (listaEventi!=null) {
			Distance d = new Distance();
			eventiOrdinati = new OrdinaEventi();
			int distance;
			for(Evento evento : listaEventi){
				distance = d.calculateBetweenAddress(sourceAddr, evento.getIndirizzo());
				eventiOrdinati.addEvento(evento, distance);
			}
		}
		return eventiOrdinati.getOrderedMap();
	}
	
	/*
	 * Metodo che data una mappa formata da coppie <Evento,Distanza>
	 * la converte in un array di eventi con affianco la distanza.
	 */
	public ArrayList<String> convertToArrayEvents(Map<Evento,Integer> map) {
		ArrayList<String> result = new ArrayList<String>();
		Iterator<Map.Entry<Evento, Integer>> it = map.entrySet().iterator();
		while (it.hasNext()) {
			Map.Entry<Evento, Integer> pairs = (Map.Entry<Evento, Integer>) it.next();
			if (pairs.getValue() == -1) {
				result.add("?? km - " + pairs.getKey().getTitolo());
			} else {
				float km = (((float) pairs.getValue()) / 1000);
				//DecimalFormat df = new DecimalFormat("#######.##");
				//km = Float.valueOf(df.format(km));
				result.add(km + " km - " + pairs.getKey().getTitolo());
			}
			//it.remove(); // avoids a ConcurrentModificationException
		}
		return result;
	}

	
}
